package concurrensy.connection_pool;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLTimeoutException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class ConnectionPoolImpl implements ConnectionPool {

	private String url;
	private String user;
	private String password;
	private final Semaphore semaphore = new Semaphore(
			ConnectionPool.MAX_POOL_SIZE, true);
	private final Queue<Connection> avaliableConnections = new ConcurrentLinkedQueue<Connection>();

	public ConnectionPoolImpl(String url, String user, String password) {
		this.url = url;
		this.user = user;
		this.password = password;
	}

	private Connection newConnection() throws SQLException {	 
		return new MyConnection(url, user, password);
	}

	@Override
	public void checkin(Connection connection) {
		avaliableConnections.add(connection);
		semaphore.release();
	}

	@Override
	public Connection checkout() throws SQLException {
		boolean freeConnectionsAvaliable = false;
		try {
			freeConnectionsAvaliable = semaphore.tryAcquire(
					ConnectionPool.WAITING_TIMEOUT, TimeUnit.MILLISECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (freeConnectionsAvaliable) {
			if (avaliableConnections.isEmpty()) {
				return newConnection();
			} else {
				return avaliableConnections.poll();
			}
		} else {
			throw new SQLTimeoutException();
		}
	}

}
